<template>
  <div
    v-if="verifyShow"
    class="verify-content"
    @mousemove="mouseMove"
    @mouseup="mouseUp"
    @click.stop
  >
    <div
      class="imgBox"
      :style="{
        width: pictureSource.data.originalWidth + 'px',
        height: pictureSource.data.originalHeight + 'px',
      }"
    >
      <img
        :src="pictureSource.data.backImage"
        style="width: 100%; height: 100%"
        alt=""
      />
      <img
        class="slider"
        :src="pictureSource.data.slidingImage"
        :style="{
          left: pictureSource.data.distance + 'px',
          top: pictureSource.data.randomY + 'px',
        }"
        :width="pictureSource.data.sliderWidth"
        :height="pictureSource.data.sliderHeight"
        alt=""
      />
      <icon-refresh class="refresh" @click="init" />
    </div>
    <div
      class="handle"
      :style="{ width: pictureSource.data.originalWidth + 'px' }"
    >
      <span
        class="bgColor"
        :style="{
          width: pictureSource.data.distance + 'px',
          background: pictureSource.data.bgColor,
        }"
      ></span>
      <span
        class="swiper"
        :style="{ left: pictureSource.data.distance + 'px' }"
        @mousedown="mouseDown"
      >
        <icon-arrow-right />
      </span>
      <span class="text">{{ pictureSource.data.verifyText }}</span>
    </div>
  </div>
</template>

<script setup lang="ts">
  import { reactive, ref } from 'vue';
  import { IconArrowRight, IconRefresh } from '@arco-design/web-vue/es/icon';
  import { getVerifyImg, postVerifyImg } from './verify';
  /**
   * 接收父组件传值
   */
  const props = defineProps({
    // 验证码类型
    verifyType: {
      type: String,
      default: 'LOGIN',
    },
  });
  const emits = defineEmits<{ (e: 'onChange', obj: object): void }>();

  const verifyShow = ref(); // 验证码显隐

  const pictureSource = reactive<any>({
    data: {
      // 验证码数据
      backImage: '', // 背景图像
      slidingImage: '', // 图像源
      originalHeight: 150, // 原始div高度
      originalWidth: 300, // 原始div宽度
      sliderWidth: 60, // 滑块高度
      sliderHeight: 60, // 滑块高度
      distance: 0, // 拼图移动距离
      flag: false, // 判断滑块是否按下
      downX: 0, // 鼠标按下位置
      bgColor: '#04ad11', // 滑动背景颜色
      verifyText: '拖动滑块解锁', // 文字提示
    },
  });

  async function init() {
    const res = await getVerifyImg(props.verifyType);

    pictureSource.data = res.data.result;
    pictureSource.data.distance = 0;
    verifyShow.value = true;
  }

  /**
   *  鼠标按下事件，开始拖动滑块
   */
  function mouseDown(e: any) {
    pictureSource.data.downX = e.clientX;
    pictureSource.data.flag = true;
  }

  /**
   * 鼠标移动事件，计算距离
   */
  function mouseMove(e: any) {
    if (pictureSource.data.flag) {
      const offset = e.clientX - pictureSource.data.downX;
      if (offset > pictureSource.data.originalWidth - 43) {
        pictureSource.data.distance = pictureSource.data.originalWidth - 43;
      } else if (offset < 0) {
        pictureSource.data.distance = 0;
      } else {
        pictureSource.data.distance = offset;
      }
    }
  }

  /**
   * 鼠标抬起事件，验证是否正确
   */
  async function mouseUp() {
    if (!pictureSource.data.flag) return false;
    pictureSource.data.flag = false;
    const params = {
      verificationEnums: props.verifyType,
      xPos: pictureSource.data.distance,
    };
    try {
      const res = await postVerifyImg(params);
      if (res.data.result) {
        pictureSource.data.bgColor = 'green';

        pictureSource.data.verifyText = '解锁成功';

        emits('onChange', {
          status: true,
          distance: pictureSource.data.distance,
        });
      } else {
        pictureSource.data.bgColor = 'red';
        pictureSource.data.verifyText = '解锁失败';
        setTimeout(() => {
          init();
        });
        emits('onChange', {
          status: false,
          distance: pictureSource.data.distance,
        });
      }
    } catch (error) {
      await init();
    }
    return '';
  }

  // 组件暴露自己的属性
  defineExpose({
    init,
    verifyShow,
  });
</script>

<style lang="less" scoped>
  .verify-content {
    padding: 10px;
    background: #fff;
    border: 1px solid #eee;
    border-radius: 5px;
    box-shadow: 1px 1px 3px #999;
  }

  .imgBox {
    width: 300px;
    height: 150px;
    position: relative;
    overflow: hidden;

    .slider {
      position: absolute;
      cursor: pointer;
    }

    .refresh {
      position: absolute;
      right: 5px;
      top: 5px;
      font-size: 20px;
      color: #fff;
      cursor: pointer;
    }
  }

  .handle {
    border: 1px solid #e4dede;
    margin-top: 5px;
    height: 42px;
    background: #ddd;
    position: relative;

    .bgColor {
      position: absolute;
      top: 0;
      left: 0;
      width: 40px;
      height: 40px;
      opacity: 0.5;
      background: #04ad11;
    }

    .swiper {
      position: absolute;
      width: 40px;
      height: 40px;
      background-color: #fff;
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .text {
      display: inline-block;
      width: inherit;
      text-align: center;
      line-height: 42px;
      font-size: 14px;
      user-select: none;
    }
  }
</style>
